#include "CockpitView.h"

#include "CockpitHBar.h"
#include "CockpitVBar.h"
// #include "CockpitCBar.h"

#include <QtWidgets/QGraphicsProxyWidget>
#include <QtGui/QPen>
#include <QtGui/QBrush>

CockpitView::CockpitView(
    QWidget * parent)
    : QWidget(parent)
{
    // if (parent == nullptr)
    // {
    //     return;
    // }
    setFocusPolicy(Qt::ClickFocus);

    setMinimumSize({400, 300});

    _top_bar = new CockpitHBar<qreal>(0
                                , [](const qreal & value) -> qreal { return CockpitBarUtils::mod0Plus360(value); }
                                , CockpitHBarUtils::ValueRisingDirection::Right
                                , CockpitHBarUtils::TextPosition::Bottom
                                );
    _top_bar->setMinimumSize({250, 50});

    _left_bar = new CockpitVBar<qreal>(0
                                , [](const qreal & value) -> qreal { return std::clamp(value, qreal(0), value); }
                                , CockpitVBarUtils::ValueRisingDirection::Up
                                , CockpitVBarUtils::TextPosition::Right
                                , { [](int) -> int
                                    {
                                        return 5;
                                    }
                                    , [](int) -> int
                                    {
                                        return 10;
                                    }
                                    , [](int) -> int
                                    {
                                        return 20;
                                    }
                                }
                                );
    _left_bar->setMinimumSize({50, 250});

    _right_bar = new CockpitVBar<qreal>(0
                                , CockpitBar<qreal>::NO_RESTRICTION
                                , CockpitVBarUtils::ValueRisingDirection::Up
                                , CockpitVBarUtils::TextPosition::Left
                                , { [](int value) -> int
                                    {
                                        int abs_value = std::abs(value);
                                        if (abs_value <= 100.0)
                                        {
                                            return 1;
                                        } else if (100.0 < abs_value && abs_value <= 1000.0)
                                        {
                                            return 10;
                                        }
                                        return 100;
                                    }
                                    , [](int value) -> int
                                    {
                                        int abs_value = std::abs(value);
                                        if (abs_value <= 100.0)
                                        {
                                            return 5;
                                        } else if (100.0 < abs_value && abs_value <= 1000.0)
                                        {
                                            return 50;
                                        }
                                        return 500;
                                    }
                                    , [](int value) -> int
                                    {
                                        int abs_value = std::abs(value);
                                        if (abs_value <= 100.0)
                                        {
                                            return 10;
                                        } else if (100.0 < abs_value && abs_value <= 1000.0)
                                        {
                                            return 100;
                                        }
                                        return 1000;
                                    }
                                }
                                );
    _right_bar->setMinimumSize({50, 250});

    // _bottom_left_bar = new CockpitCBar();
    // _bottom_left_bar->setMinimumSize({50, 250});

    // _bottom_right_bar = new CockpitCBar();
    // _bottom_right_bar->setMinimumSize({50, 250});

    auto vbox_layout = new QVBoxLayout(this);
    vbox_layout->addWidget(_top_bar, 1);

    auto hbox_layout = new QHBoxLayout;
    hbox_layout->addWidget(_left_bar, 1);

    // auto hl = new QVBoxLayout();
    // hl->addWidget(_view3d_container, 2);

    // _bhbox_layout = new QHBoxLayout();
    // _bhbox_layout->addWidget(_bottom_left_bar, 1);
    // _bhbox_layout->addWidget(_bottom_right_bar, 1);
    // hl->addLayout(_bhbox_layout, 1);

    // _hbox_layout->addLayout(hl, 4);
    _aviagorizont = new CockpitAviagorizont<qreal>({ 0, 0 });
    _variometer = new CockpitVariometer<qreal>({ 0, 0 });
    auto l1 = new QHBoxLayout;
    l1->addWidget(_aviagorizont);
    l1->addWidget(_variometer);
    hbox_layout->addLayout(l1, 3);
    // _hbox_layout->addWidget(_aviagorizont, 1);

    hbox_layout->addWidget(_right_bar, 1);

    vbox_layout->addLayout(hbox_layout, 4);
}

void CockpitView::keyPressEvent(QKeyEvent * event)
{
    if (event->isAutoRepeat())
    {
        return;
    }

    auto key = event->text();
    if (_key_states.find(key) == _key_states.end() || !_key_states[key])
    {
        _key_states[key] = true;
        emit pressKey(key);
    }
}

void CockpitView::keyReleaseEvent(QKeyEvent * event)
{
    if (event->isAutoRepeat())
    {
        return;
    }

    auto key = event->text();
    if (_key_states.find(key) != _key_states.end() && _key_states[key])
    {
        _key_states[key] = false;
        emit releaseKey(key);
    }
}

void CockpitView::handleChangedHeight(qreal height)
{
    _right_bar->setValue(height);
    _right_bar->update();
}

void CockpitView::handleChangedAngles(qreal pitch, qreal course, qreal roll)
{
    // _left_bar->setValue(pitch);
    // _left_bar->update();

    _top_bar->setValue(course);
    _top_bar->update();

    // _bottom_left_bar->setValue(pitch);
    // _bottom_left_bar->update();

    // _bottom_right_bar->setValue(roll);
    // _bottom_right_bar->update();

    _aviagorizont->setValue({pitch, roll});
    _aviagorizont->update();
}

void CockpitView::handleChangedSpeed(qreal speed)
{
    _left_bar->setValue(speed);
    _left_bar->update();
}

void CockpitView::handleChangedVerticalSpeedSlide(qreal vertical_speed, qreal slide)
{
    _variometer->setValue({vertical_speed, slide});
    _variometer->update();
}
